﻿namespace HuwmanCode.ComponentModel.Composition.Hosting

open System
open System.IO
open System.Reflection
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open System.ComponentModel.Composition.Primitives

open HuwmanCode

/// <summary>
/// A strong name assembly catalog for MEF.
/// </summary>
type StrongNameCatalog (path:String, [<ParamArray>] trustedKeys:byte[][]) =
    inherit ComposablePartCatalog ()
    let trustedFiles =
        Directory.GetFiles (path)
        |> Array.filter (fun file -> file |> Path.GetExtension |> fun ext -> ext = ".dll" || ext = ".exe")
        |> Array.choose (fun file -> file |> Option.tryMake (fun f -> f,AssemblyName.GetAssemblyName f))
        |> Array.choose (fun (file,assemblyName) -> assemblyName |> Option.tryMake (fun an -> file,an.GetPublicKey ()))
        |> Array.filter (fun (file,pk) -> trustedKeys |> Array.exists (fun tpk -> tpk = pk))
        |> Array.map (fun (file,_) -> file)

    let aggregateCatalog = 
        trustedFiles
        |> Array.map (fun file -> new AssemblyCatalog (file) :> ComposablePartCatalog)
        |> fun catalogs -> new AggregateCatalog (catalogs)

    member this.TrustedAssemblies = 
        trustedFiles |> Array.map (fun file -> Assembly.LoadFile file)

    override this.Parts
        with get () = aggregateCatalog.Parts

    override this.GetExports definition =
        aggregateCatalog.GetExports definition